package io.gps.datatransfer;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import io.gps.datatransfer.codec.TCPCodecFactory;
import io.gps.datatransfer.command.DevServer;
import io.gps.datatransfer.command.GpsMsg;
import io.gps.datatransfer.command.SendMsgPack;
import io.gps.datatransfer.task.InterManager;
import io.gps.datatransfer.task.taskentity.CenterConnWork;
import io.gps.datatransfer.utils.ByteUtils;
import io.gps.datatransfer.utils.SysDef;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;


/**
 * 转发服务控制器
 *
 * @author bcs
 * @version 2.0, $Date: 2020-11-26 13:06:17 $
 */
public class CenterChannel extends IoHandlerAdapter {

    public boolean isSendSta = false;
    private Logger logger = Logger.getLogger(CenterChannel.class);
//    private ScheduledExecutorService gpsloginses = Executors.newScheduledThreadPool(1);

    /**
     * 上送服务器对象
     */
    public DevServer devServer;
    public String sim;

    public SocketConnector connector=null;
    /**
     * 通信会话session
     */
    public IoSession cssession=null;
    public long lastHandTime = 0;
    public ConnectFuture connectFuture;
    public long last0100Time = 0;

    /**
     * 车辆 指令队列
     */
    private ConcurrentLinkedQueue<IoBuffer> queueMsg = new ConcurrentLinkedQueue<IoBuffer>();


    public CenterChannel(DevServer devServer, String sim) {
        this.devServer = devServer;
        this.sim = sim;
        this.connect();
    }

    public DevServer getDevServer() {
        return devServer;
    }

    /**
     * 链接
     */
    public void connect(){
        this.connector = new NioSocketConnector();
        this.connector.setHandler(this);
        int ideleTime = 40;
        if (SysDef.IS_SET_ONE || !devServer.isIsmaster()) {
            ideleTime = 20;
        }
        this.connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TCPCodecFactory(true)));
        this.connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, ideleTime);
        this.connector.getSessionConfig().setMaxReadBufferSize(2048);
        this.connector.getSessionConfig().setKeepAlive(true);
        this.connector.getSessionConfig().setSoLinger(0);
        InterManager.mexecutor.execute(new CenterConnWork(this));
        //this.gpsloginses.scheduleAtFixedRate(new CenterConnWork(this),0, 20, TimeUnit.SECONDS);

    }

    public void connectServer() throws Exception {
        if(cssession == null){
            isSendSta=false;
            this.connectFuture = connector.connect(new InetSocketAddress(this.devServer.getIp(), this.devServer.getPort()));
            this.connectFuture.awaitUninterruptibly(2000);
            if(!this.connectFuture.isDone()) {
                disconnect("connectServer 链接失败");
            }
        }
    }




    /**
     * 关闭session
     */
    public void disconnect(String src) {
        logger.info(this.sim+"-------------------------"+src+"-------销毁回话"+this.devServer.getServerid());
        if (this.cssession != null) {
            this.cssession.closeNow();
            this.cssession = null;
        }
    }

    /**
     * 关闭session
     */
    public void disconnectALL(String src) {
        logger.info(this.sim+"-------------------------"+src+"-------销毁回话"+this.devServer.getServerid());
        if (this.cssession != null) {
            this.cssession.closeNow();
            this.cssession = null;
        }

//        this.gpsloginses.shutdown();
        if(connector!=null){
            connector.dispose();
        }
        String tempkey=SysDef.getserverkey(this.sim ,this.devServer.getServerid());
        SysDef.sim_server_center.remove(tempkey);
    }


    @Override
    public void sessionCreated(IoSession session) throws Exception {
        this.cssession = session;
       Map<String,String> carMap= SysDef.CAR_LIST.get(this.sim);
       long nowtime=System.currentTimeMillis();
       if(isSendSta==false&&(last0100Time==0||nowtime-last0100Time>30000)){
           last0100Time=nowtime;
           lastHandTime=nowtime;
           int sheng=41;
           int shi=1000; int cpys=0;
           String cph="0000000";
           if(carMap!=null){
               if(carMap.size()>4){
                   sheng=Integer.parseInt(carMap.get("SHENG"));
                   shi=Integer.parseInt(carMap.get("SHI"));
               }
               cpys=Integer.parseInt(carMap.get("CPYS"));
               cph=carMap.get("CPH");
           }
           IoBuffer ioBuffer=SendMsgPack.get0100(this.sim,sheng,shi,cpys,cph);
           this.cssession.write(ioBuffer);
           logger.info(this.sim + " 与中心服务器: " + this.devServer.getServerid() + " 发起注册:"+ByteUtils.getSouDataLog(ioBuffer));
       }
    }

    @Override
    public void sessionClosed(IoSession session) throws Exception {
        this.disconnect("sessionClosed 回话关闭");
    }


    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        this.disconnect("sessionIdle 回话关闭");
    }

    @Override
    public void messageReceived(IoSession session, Object message)
            throws Exception {
        GpsMsg gpsMsg = (GpsMsg) message;
        IoBuffer sendObj = null;
        boolean isSend=false;
        if (gpsMsg.getSrc() != null) {
            if(gpsMsg.getMsgid() == 0x8100){
                // 注册成功，发起鉴权
                IoBuffer sendOBj= SendMsgPack.Get0100ASK(this.sim,gpsMsg.getSrc());
                if(sendOBj!=null){
                    logger.info(this.sim + " 中心服务器: " + this.devServer.getServerid() + " 0x8100");
                    lastHandTime=System.currentTimeMillis();
                    this.cssession.write(sendOBj);
                    isSendSta=true;
                }
            }else if(gpsMsg.getMsgid() == 0x8001){
                if(this.devServer.isIsmaster()){
                    isSend=true;
                }
            }else{
                isSend=true;
            }
            if (isSend) {
                sendObj =gpsMsg.getSrc();
            }
        }
        if (sendObj != null) {
            IoSession downSession= SysDef.sim_session.get(gpsMsg.getSim());
            if(downSession!=null){
                downSession.write(sendObj);
                if (SysDef.IS_LOG) {
                    logger.error("实际向设备下发：" + ByteUtils.getSouDataLog(sendObj));
                }
            }

        }

    }

    @Override
    public void exceptionCaught(IoSession session, Throwable cause)
            throws Exception {
        this.disconnect("exceptionCaught 链接异常");

        logger.error(cause.getMessage(), cause);
    }

    public void addMsg(IoBuffer iob) {
        this.queueMsg.add(iob);
        InterManager.mexecutor.execute(new CenterConnWork(this));
    }

    public void sendMsg() {
        if (isSendSta==true&&this.cssession != null && this.cssession.isConnected()) {
            if (!queueMsg.isEmpty()) {
                for (int i = 0; i < 100; i++) {
                    IoBuffer iob = queueMsg.poll();
                    if (iob != null) {
                        WriteFuture wf = this.cssession.write(iob);
                        boolean sendsta = wf.isWritten();
                        if (SysDef.IS_LOG) {
                            logger.error("TO" + (this.devServer.isIsmaster() ? "主" : "从") + "服务器" + this.devServer.getServerid() +sendsta+ "发送数据：" + ByteUtils.getSouDataLog(iob));
                        }
                    } else {
                        i = 101;
                    }
                }
            }
        }
    }
}

